package com.logger.aop.aspect;

import android.util.Log;

import com.logger.Logger;
import com.logger.LoggerFactory;
import com.logger.MLogger;
import com.logger.aop.internal.StopWatch;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.util.concurrent.TimeUnit;

/**
 * 定义具体的切面
 * <p>
 * Created by chenxunlin01 on 2016/12/23.
 */
@Aspect
public class TraceAspect {

    private static Logger logger = LoggerFactory.getLogger("TraceAspect");

    private static final String POINTCUT_METHOD =
            "execution(@aop.annotation.DebugTimeTrace * *(..))";

    private static final String POINTCUT_CONSTRUCTOR =
            "execution(@aop.annotation.DebugTimeTrace *.new(..))";

    @Pointcut(POINTCUT_METHOD)
    public void methodAnnotatedWithDebugTrace() {
    }

    @Pointcut(POINTCUT_CONSTRUCTOR)
    public void constructorAnnotatedDebugTrace() {
    }

    @Around("methodAnnotatedWithDebugTrace()||constructorAnnotatedDebugTrace()")
    public Object traceTimeJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginNanos = System.nanoTime();
        Object result = joinPoint.proceed();
        long endNanos = System.nanoTime();

        long totalMillis = TimeUnit.NANOSECONDS.toMillis(endNanos - beginNanos);

        logger.append(createLogMsg(joinPoint, totalMillis)).debug();

        return result;
    }

    /**
     * @param joinPoint
     * @return
     */
    private String createLogMsg(ProceedingJoinPoint joinPoint, long totalTime) {
        Signature signature = joinPoint.getSignature();
        String className = signature.getDeclaringType().getName();
        String methodName = signature.getName();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(getStackTrace(className, methodName));
        stringBuilder.append("total-time:");
        stringBuilder.append(totalTime);
        stringBuilder.append("ms");
        return stringBuilder.toString();
    }

    private String getStackTrace(String className, String methodName) {
        StringBuilder sb = new StringBuilder("");
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        StackTraceElement element;
//      正常的检查
        for (int i = 0, size = elements.length; i < size; i++) {
            element = elements[i];
            if (element.getClassName().equals(className) && element.getMethodName().equals(methodName)) {
                String eleClassName = element.getFileName().replace(".java", "");
                sb.append(className.substring(className.indexOf(eleClassName)));
                sb.append(".");
                sb.append(element.getMethodName());
                String eleStr = element.toString();
                int start = eleStr.indexOf("(");
                sb.append(eleStr.substring(start));
                sb.append("\n");
                return sb.toString();
            }
        }

        return sb.toString();
    }
}
